package com.hl.payServer.util.xml;

import com.hl.payServer.exception.XmlException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

/**
 * 简陋的XML读取器
 */
public class XmlReaders {
    private static final Logger logger = LoggerFactory.getLogger(XmlReaders.class);
    public static DocumentBuilder builder = null;
    private Document document;
    private XmlReaders(){}
    static {
        try {
            /*
            腾讯官方提供的解决漏洞的代码
             */
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
            documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
            documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
            documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
            documentBuilderFactory.setXIncludeAware(false);
            documentBuilderFactory.setExpandEntityReferences(false);
            builder = documentBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            logger.error("XmlReaders builder异常", e);
            throw new XmlException("init xml failed");
        }
    }

    public static XmlReaders create(String xml){
        XmlReaders xmlReaders=null;
        try {
            xmlReaders=create(new ByteArrayInputStream(xml.getBytes("utf-8")));
        } catch (UnsupportedEncodingException e) {
            logger.error("XmlReaders create异常(xml)", e);
        }
        return xmlReaders;
    }

    public static XmlReaders create(InputStream inputStream){
        XmlReaders readers = new XmlReaders();
        try {
            readers.document = builder.parse(inputStream);
        } catch (Exception e) {
            logger.error("XmlReaders create异常(inputStream)", e);
            throw new XmlException("Xmls create fail", e);
        }
        return readers;
    }

    public Node getNode(String tagName){
        NodeList nodes = document.getElementsByTagName(tagName);
        if (nodes.getLength() <= 0){
            return null;
        }
        return nodes.item(0);
    }
    /**
     * 获取某个节点的文本内容，若有多个该节点，只会返回第一个
     * @param tagName 标签名
     * @return 文本内容，或NULL
     */
   /* public String getNodeStr(String tagName){
        Node node = getNode(tagName);
        return node == null ? null : node.getTextContent();
    }*/

    /**
     * 获取某个节点的Float，若有多个该节点，只会返回第一个
     * @param tagName 标签名
     * @return Float值，或NULL
     */
    /*public Float getNodeFloat(String tagName){
        String nodeContent = getNodeStr(tagName);
        return nodeContent == null ? null : Float.valueOf(nodeContent);
    }*/

    /**
     * 解析xml字符串
     * @param protocolXML
     * @return
     */
    public static Map<String, Object> readXMLString(String protocolXML) {
        protocolXML = protocolXML.replaceAll("(\\r|\\n)", "");
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Document doc = builder.parse(new InputSource(new StringReader(protocolXML)));
            Element root = doc.getDocumentElement();
            NodeList books = root.getChildNodes();
            if (books != null) {
                for (int i = 0; i < books.getLength(); i++) {
                    Node book = books.item(i);
                    map.put(book.getNodeName(), book.getFirstChild().getNodeValue());
                }
            }
        } catch (Exception e) {
            logger.error("XmlReaders readXMLString异常", e);
        }
        return map;
    }
}
